home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / lib / python2.6 / dist-packages / gst-0.10 / gst / extend / discoverer.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-04-20  |  10.9 KB  |  306 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. '''
  5. Class and functions for getting multimedia information about files
  6. '''
  7. import os.path as os
  8. import gobject
  9. import gst
  10. from gst.extend.pygobject import gsignal
  11.  
  12. class Discoverer(gst.Pipeline):
  13.     """
  14.     Discovers information about files.
  15.     This class is event-based and needs a mainloop to work properly.
  16.     Emits the 'discovered' signal when discovery is finished.
  17.  
  18.     The 'discovered' callback has one boolean argument, which is True if the
  19.     file contains decodable multimedia streams.
  20.     """
  21.     __gsignals__ = {
  22.         'discovered': (gobject.SIGNAL_RUN_FIRST, None, (gobject.TYPE_BOOLEAN,)) }
  23.     mimetype = None
  24.     audiocaps = { }
  25.     videocaps = { }
  26.     videowidth = 0
  27.     videoheight = 0
  28.     videorate = 0
  29.     audiofloat = False
  30.     audiorate = 0
  31.     audiodepth = 0
  32.     audiowidth = 0
  33.     audiochannels = 0
  34.     audiolength = 0x0L
  35.     videolength = 0x0L
  36.     is_video = False
  37.     is_audio = False
  38.     otherstreams = []
  39.     finished = False
  40.     sinknumber = 0
  41.     tags = { }
  42.     
  43.     def __init__(self, filename, max_interleave = 1, timeout = 3000):
  44.         """
  45.         filename: str; absolute path of the file to be discovered.
  46.         max_interleave: int or float; the maximum frame interleave in seconds.
  47.             The value must be greater than the input file frame interleave
  48.             or the discoverer may not find out all input file's streams.
  49.             The default value is 1 second and you shouldn't have to change it,
  50.             changing it mean larger discovering time and bigger memory usage.
  51.         timeout: int; duration in ms for the discovery to complete.
  52.         """
  53.         gobject.GObject.__init__(self)
  54.         self.mimetype = None
  55.         self.audiocaps = { }
  56.         self.videocaps = { }
  57.         self.videowidth = 0
  58.         self.videoheight = 0
  59.         self.videorate = gst.Fraction(0, 1)
  60.         self.audiofloat = False
  61.         self.audiorate = 0
  62.         self.audiodepth = 0
  63.         self.audiowidth = 0
  64.         self.audiochannels = 0
  65.         self.audiolength = 0x0L
  66.         self.videolength = 0x0L
  67.         self.is_video = False
  68.         self.is_audio = False
  69.         self.otherstreams = []
  70.         self.finished = False
  71.         self.tags = { }
  72.         self._success = False
  73.         self._nomorepads = False
  74.         self._timeoutid = 0
  75.         self._timeout = timeout
  76.         self._max_interleave = max_interleave
  77.         if not os.path.isfile(filename):
  78.             self.debug("File '%s' does not exist, finished" % filename)
  79.             self.finished = True
  80.             return None
  81.         self.src = gst.element_factory_make('filesrc')
  82.         self.src.set_property('location', filename)
  83.         self.src.set_property('blocksize', 1000000)
  84.         self.dbin = gst.element_factory_make('decodebin')
  85.         self.add(self.src, self.dbin)
  86.         self.src.link(self.dbin)
  87.         self.typefind = self.dbin.get_by_name('typefind')
  88.         self.typefind.connect('have-type', self._have_type_cb)
  89.         self.dbin.connect('new-decoded-pad', self._new_decoded_pad_cb)
  90.         self.dbin.connect('no-more-pads', self._no_more_pads_cb)
  91.         self.dbin.connect('unknown-type', self._unknown_type_cb)
  92.  
  93.     
  94.     def _timed_out_or_eos(self):
  95.         if not not (self.is_audio) or not (self.is_video):
  96.             if (self.is_audio or not (self.audiocaps) or self.is_video) and not (self.videocaps):
  97.                 self._finished(False)
  98.             else:
  99.                 self._finished(True)
  100.  
  101.     
  102.     def _finished(self, success = False):
  103.         self.debug('success:%d' % success)
  104.         self._success = success
  105.         self.bus.remove_signal_watch()
  106.         if self._timeoutid:
  107.             gobject.source_remove(self._timeoutid)
  108.             self._timeoutid = 0
  109.         
  110.         gobject.idle_add(self._stop)
  111.         return False
  112.  
  113.     
  114.     def _stop(self):
  115.         self.debug('success:%d' % self._success)
  116.         self.finished = True
  117.         self.set_state(gst.STATE_READY)
  118.         self.debug('about to emit signal')
  119.         self.emit('discovered', self._success)
  120.  
  121.     
  122.     def _bus_message_cb(self, bus, message):
  123.         if message.type == gst.MESSAGE_EOS:
  124.             self.debug('Got EOS')
  125.             self._timed_out_or_eos()
  126.         elif message.type == gst.MESSAGE_TAG:
  127.             for key in message.parse_tag().keys():
  128.                 self.tags[key] = message.structure[key]
  129.             
  130.         elif message.type == gst.MESSAGE_ERROR:
  131.             self.debug('Got error')
  132.             self._finished()
  133.         
  134.  
  135.     
  136.     def discover(self):
  137.         '''Find the information on the given file asynchronously'''
  138.         self.debug('starting discovery')
  139.         if self.finished:
  140.             self.emit('discovered', False)
  141.             return None
  142.         self.bus = self.get_bus()
  143.         self.bus.add_signal_watch()
  144.         self.bus.connect('message', self._bus_message_cb)
  145.         self._timeoutid = gobject.timeout_add(self._timeout, self._timed_out_or_eos)
  146.         self.info('setting to PLAY')
  147.         if not self.set_state(gst.STATE_PLAYING):
  148.             self._finished()
  149.         
  150.  
  151.     
  152.     def _time_to_string(self, value):
  153.         '''
  154.         transform a value in nanoseconds into a human-readable string
  155.         '''
  156.         ms = value / gst.MSECOND
  157.         sec = ms / 1000
  158.         ms = ms % 1000
  159.         min = sec / 60
  160.         sec = sec % 60
  161.         return '%2dm %2ds %3d' % (min, sec, ms)
  162.  
  163.     
  164.     def print_info(self):
  165.         '''prints out the information on the given file'''
  166.         if not self.finished:
  167.             return None
  168.         if not self.mimetype:
  169.             print 'Unknown media type'
  170.             return None
  171.         print 'Mime Type :\t', self.mimetype
  172.         if not (self.is_video) and not (self.is_audio):
  173.             return None
  174.         print 'Length :\t', self._time_to_string(max(self.audiolength, self.videolength))
  175.         print '\tAudio:', self._time_to_string(self.audiolength), '\tVideo:', self._time_to_string(self.videolength)
  176.         if self.is_video and self.videorate:
  177.             print 'Video :'
  178.             print '\t%d x %d @ %d/%d fps' % (self.videowidth, self.videoheight, self.videorate.num, self.videorate.denom)
  179.             if self.tags.has_key('video-codec'):
  180.                 print '\tCodec :', self.tags.pop('video-codec')
  181.             
  182.         
  183.         if self.is_audio:
  184.             print 'Audio :'
  185.             if self.audiofloat:
  186.                 print '\t%d channels(s) : %dHz @ %dbits (float)' % (self.audiochannels, self.audiorate, self.audiowidth)
  187.             else:
  188.                 print '\t%d channels(s) : %dHz @ %dbits (int)' % (self.audiochannels, self.audiorate, self.audiodepth)
  189.             if self.tags.has_key('audio-codec'):
  190.                 print '\tCodec :', self.tags.pop('audio-codec')
  191.             
  192.         
  193.         for stream in self.otherstreams:
  194.             if not stream == self.mimetype:
  195.                 print 'Other unsuported Multimedia stream :', stream
  196.                 continue
  197.         
  198.         if self.tags:
  199.             print 'Additional information :'
  200.             for tag in self.tags.keys():
  201.                 print '%20s :\t' % tag, self.tags[tag]
  202.             
  203.         
  204.  
  205.     
  206.     def _no_more_pads_cb(self, dbin):
  207.         self.info('no more pads')
  208.         self._nomorepads = True
  209.  
  210.     
  211.     def _unknown_type_cb(self, dbin, pad, caps):
  212.         self.debug('unknown type : %s' % caps.to_string())
  213.         self.otherstreams.append(caps.to_string())
  214.         if not (self.is_video) and not (self.is_audio):
  215.             self.finished = True
  216.             self._finished()
  217.         
  218.  
  219.     
  220.     def _have_type_cb(self, typefind, prob, caps):
  221.         self.mimetype = caps.to_string()
  222.  
  223.     
  224.     def _notify_caps_cb(self, pad, args):
  225.         caps = pad.get_negotiated_caps()
  226.         if not caps:
  227.             pad.info('no negotiated caps available')
  228.             return None
  229.         pad.info('caps:%s' % caps.to_string())
  230.         q = gst.query_new_duration(gst.FORMAT_TIME)
  231.         pad.info('sending duration query')
  232.         if pad.get_peer().query(q):
  233.             (format, length) = q.parse_duration()
  234.             if format == gst.FORMAT_TIME:
  235.                 pad.info('got duration (time) : %s' % (gst.TIME_ARGS(length),))
  236.             else:
  237.                 pad.info('got duration : %d [format:%d]' % (length, format))
  238.         else:
  239.             length = -1
  240.             gst.warning('duration query failed')
  241.         if 'audio' in caps.to_string():
  242.             self.audiocaps = caps
  243.             self.audiolength = length
  244.             self.audiorate = caps[0]['rate']
  245.             self.audiowidth = caps[0]['width']
  246.             self.audiochannels = caps[0]['channels']
  247.             if 'x-raw-float' in caps.to_string():
  248.                 self.audiofloat = True
  249.             else:
  250.                 self.audiodepth = caps[0]['depth']
  251.             if self._nomorepads:
  252.                 pass
  253.             None if not (self.is_video) or self.videocaps else self.videocaps
  254.         elif 'video' in caps.to_string():
  255.             self.videocaps = caps
  256.             self.videolength = length
  257.             self.videowidth = caps[0]['width']
  258.             self.videoheight = caps[0]['height']
  259.             self.videorate = caps[0]['framerate']
  260.             if self._nomorepads:
  261.                 pass
  262.             None if not (self.is_audio) or self.audiocaps else self.audiocaps
  263.         
  264.  
  265.     
  266.     def _new_decoded_pad_cb(self, dbin, pad, is_last):
  267.         caps = pad.get_caps()
  268.         gst.info('caps:%s' % caps.to_string())
  269.         if 'audio' in caps.to_string():
  270.             self.is_audio = True
  271.         elif 'video' in caps.to_string():
  272.             self.is_video = True
  273.         else:
  274.             self.warning('got a different caps.. %s' % caps.to_string())
  275.             return None
  276.         if 'audio' in caps.to_string() and not (self.is_video) and not (self.is_audio):
  277.             self.debug('is last, not video or audio')
  278.             self._finished(False)
  279.             return None
  280.         pad.info('adding queue->fakesink')
  281.         if not 'audio' in caps.to_string() or 'audio':
  282.             pass
  283.         fakesink = gst.element_factory_make('fakesink', 'fakesink%d-%s' % (self.sinknumber, 'video'))
  284.         self.sinknumber += 1
  285.         queue = gst.element_factory_make('queue')
  286.         queue.props.min_threshold_time = int(self._max_interleave * gst.SECOND)
  287.         queue.props.max_size_time = int(2 * self._max_interleave * gst.SECOND)
  288.         queue.props.max_size_bytes = 0
  289.         queue.props.max_size_buffers = int(100 * self._max_interleave)
  290.         
  291.         def _disable_min_threshold_cb(queue):
  292.             queue.props.min_threshold_time = 0
  293.             queue.disconnect(signal_id)
  294.  
  295.         signal_id = queue.connect('overrun', _disable_min_threshold_cb)
  296.         self.add(fakesink, queue)
  297.         queue.link(fakesink)
  298.         sinkpad = fakesink.get_pad('sink')
  299.         queuepad = queue.get_pad('sink')
  300.         sinkpad.connect('notify::caps', self._notify_caps_cb)
  301.         queue.set_state(gst.STATE_PLAYING)
  302.         fakesink.set_state(gst.STATE_PLAYING)
  303.         gst.info('finished here')
  304.  
  305.  
  306.